#region Licence
// Copyright (c) 2008 James Gregory (james@jagregory.com)
// All rights reserved.
// 
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
// 
//     * Redistributions of source code must retain the above copyright notice,
//     this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above copyright notice,
//     this list of conditions and the following disclaimer in the documentation
//     and/or other materials provided with the distribution.
//     * Neither the name of James Gregory nor the names of its
//     contributors may be used to endorse or promote products derived from this
//     software without specific prior written permission.
// 
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#endregion

using System.Collections;
using System.Collections.Generic;

namespace JAGregory.BooPlugin.Language.Members
{
    public class MemberDeclarationCollection : ICollection<MemberDeclaration>
    {
        private readonly List<MemberDeclaration> members = new List<MemberDeclaration>();
        
        public void Add(MemberDeclaration item)
        {
            if (item == null) return;

            if (Contains(item.Name))
            {
                foreach (MemberDeclaration dec in members)
                {
                    if (dec.Name == item.Name)
                    {
                        if (dec.MemberType == item.MemberType)
                            dec.Signatures.AddRange(item.Signatures);
                        else
                            members.Add(dec);
                    }
                }
            }
            else
                members.Add(item);
        }

        public MemberDeclaration this[int index]
        {
            get { return members[index]; }
            set { members[index] = value; }
        }

        public void Clear()
        {
            members.Clear();
        }

        public bool Contains(MemberDeclaration item)
        {
            return members.Contains(item);
        }

        public bool Contains(string memberName)
        {
            return members.Exists(delegate(MemberDeclaration declaration) {
                return declaration.Name == memberName;
            });
        }

        public void CopyTo(MemberDeclaration[] array, int arrayIndex)
        {
            foreach (MemberDeclaration mem in members)
            {
                array[arrayIndex] = mem;
                arrayIndex++;
            }
        }

        public int Count
        {
            get { return members.Count; }
        }

        public bool IsReadOnly
        {
            get { return false; }
        }

        public bool Remove(MemberDeclaration item)
        {
            return members.Remove(item);
        }

        public void Sort()
        {
            members.Sort(delegate(MemberDeclaration x, MemberDeclaration y) {
                return string.Compare(x.Name, y.Name);
            });
        }

        public IEnumerator<MemberDeclaration> GetEnumerator()
        {
            return members.GetEnumerator();
        }

        IEnumerator IEnumerable.GetEnumerator()
        {
            return new ArrayList(members).GetEnumerator();
        }

        internal void AddRange(List<MemberDeclaration> list)
        {
            foreach (MemberDeclaration mem in list)
            {
                Add(mem);
            }
        }

        public int IndexOf(string name)
        {
            return members.FindIndex(delegate(MemberDeclaration declaration) {
                return declaration.Name == name;
            });
        }
    }
}